#ifndef _RFID_PROTOCOL_H_
#define _RFID_PROTOCOL_H_

#include "rfid_board.h"

#if _RFID_FUNCTION_ENABLE_

// 离线卡字段长度
#define OFFLINE_CARD_CAPTCHA_BIT_LENGTH                   4
// 离线卡随机数长度
#define OFFLINE_CARD_RANDOM_BIT_LENGTH                    4

// 虚拟卡号字段长度
#define VIRTUAL_CARD_SERIAL_NUMBER_LENGTH                 (USER_AUTHENTICATION_KEY_LENGTH)

// 离线卡时间段上限
#define OFFLINE_CARD_MAX_TIME_SLOTS                       12
// 房间上限
#define OFFLINE_CARD_MAX_ROOM_QUANTITIES                  55

// 验证码固定内容 - 杨格
#define OFFLINE_CARD_CAPTCHA_DATA_YG                      "YGV3"
// 验证码固定内容 - 华住
#define OFFLINE_CARD_CAPTCHA_DATA_HZ                      "HWGP"

// 密钥后缀内容 - 杨格
#define OFFLINE_CARD_KEY_SUFFIX_YG                        "1EYJxEG9Kr"
// 密钥后缀内容 - 华住
#define OFFLINE_CARD_KEY_SUFFIX_HZ                        "6dVAIY9fAS"

/**
 * @brief 顶替错误码
 *
 */
typedef enum
{
  RFID_PROTOCOL_SUCCESS,    // 成功
  RFID_PROTOCOL_ID_ERROR,   // 编码错误
  RFID_PROTOCOL_TIME_ERROR, // 时间错误
} ReplaceErrorCode_t;

/**
 * @brief 描述时间区域格式
 *
 */
typedef struct
{
  uint8_t StartHour;   // 开始时
  uint8_t StartMinute; // 开始分
  uint8_t EndHour;     // 结束时
  uint8_t EndMinute;   // 结束分
} CardTimeCycle_t;

/**
 * @brief 时间戳转换
 *
 */
typedef union
{
  uint32_t BasicCycle;       // 基本周期
  CardTimeCycle_t TimeCycle; // 周期时间段
} CardCycleUnion_t;

/**
 * @brief 卡片房间信息
 *
 */
typedef struct
{
  uint32_t RoomId;   // 房间号
  uint8_t FloorId;   // 楼层
  uint8_t GardenId;  // 园区号
  uint8_t SubroomId; // 子房间号
  uint8_t BuildId;   // 楼栋
} CardRoomAttribute_t;

/**
 * @brief 卡功能定义
 *
 */
typedef union
{
  uint8_t Ident;

  struct 
  {
    uint8_t Recover     : 1; // 可开反锁
    uint8_t NormalOpen  : 1; // 常开
    uint8_t Replace     : 1; // 顶替
    uint8_t ClearEn     : 1; // 保洁
    uint8_t Reserve     : 4; // 预留
  } ControlBit;

  struct
  {
    uint8_t ReplaceInfo : 1; // 顶替信息
    uint8_t Cardholder  : 1; // 持卡人
    uint8_t Log         : 1; // 日志
    uint8_t Reserve     : 5; // 预留
  } ClearBit;
} CardFunction_t;

/**
 * @brief 离线卡数据结构
 *
 */
typedef struct
{
  uint8_t Date;                                                 // 日期
  uint16_t Length;                                              // 数据总长
  uint8_t CardType;                                             // 卡类型
  uint32_t Reserved;                                            // 保留
  uint32_t Grouping;                                            // 分组
  uint16_t ReplaceId;                                           // 顶替编码
  uint8_t NumberOfRoom;                                         // 可操作房间数量
  uint32_t EndTimestamp;                                        // 结束时间
  uint32_t StartTimestamp;                                      // 开始时间
  uint8_t NumberOfTimeSlots;                                    // 时间段数量
  CardFunction_t CardFunction;                                  // 卡功能
  uint16_t TranslationCategory;                                 // 类别
  uint8_t Random[OFFLINE_CARD_RANDOM_BIT_LENGTH];               // 随机数
  uint8_t Captcha[OFFLINE_CARD_CAPTCHA_BIT_LENGTH];             // 验证码
  CardCycleUnion_t Time[OFFLINE_CARD_MAX_TIME_SLOTS];           // 有效时间段
  uint8_t CardSerialNumber[VIRTUAL_CARD_SERIAL_NUMBER_LENGTH];  // 虚拟卡号
  CardRoomAttribute_t RoomId[OFFLINE_CARD_MAX_ROOM_QUANTITIES]; // 房间信息
} RfidProtocolFormat_t;

// 离线卡数据解析
typedef void (*OfflineCardPrase_t)(RfidProtocolFormat_t *);

// 离线卡数据数据更新
typedef bool (*OfflineCardDataUpdate_t)(RfidProtocolFormat_t *);

/**
 * @brief 验证卡片数据有效性
 * 
 * @param pDataIn             - 待验证的数据
 * @param pCardSerialNumberIn - 卡片序列号
 * @param CardProtocol        - 卡片协议
 * @return bool               - 验证结果（true：成功 false：失败）
 */
extern bool RfidValidateCardDataValidity(const uint8_t *pDataIn, const uint8_t *pCardSerialNumberIn, uint8_t CardProtocol);

/**
 * @brief 验证厂商卡数据有效性
 * 
 * @param pDataIn  - 待验证的数据
 * @param DataSize - 数据长度
 * @param pDataOut - 修改后的数据
 * @param pSizeOut - 修改后的数据长度
 * @return bool    - 验证结果（true：成功 false：失败）
 */
extern bool RfidVerifyCardDataValidity(const uint8_t *pDataIn, uint16_t DataSize, uint8_t *pDataOut, uint16_t *pSizeOut);

#endif
#endif
